# -*- coding: ISO-8859-1 -*-
#############################################
## (C)opyright by Dirk Holtwick, 2002-2007 ##
## All rights reserved                     ##
#############################################

__reversion__ = "$Revision: 20 $"
__author__    = "$Author: holtwick $"
__date__      = "$Date: 2007-10-09 12:58:24 +0200 (Di, 09 Okt 2007) $"

import logging
log = logging.getLogger(__name__)

try:
    import cStringIO as StringIO
except:
    import StringIO

import base64
import re
import urlparse
import mimetypes
import urllib2
import os.path

# Just supports base64 for the moment
_rx_datauri = re.compile("^data:(?P<mime>[a-z]+/[a-z]+);base64,(?P<data>.*)$", re.M|re.DOTALL)

class FileObject:

    """
    Universal file object that loads:

    - Data URI
    - Remote URL
    - Local files

    Returns

    - String data
    - File object
    - Mime type
    - Basepath
    - Status informations like: local file, file not found
    """

    def __init__(self, uri, basepath=None):

        self.basepath = basepath
        self.mimetype = None
        self.file = None
        self.data = None
        self.uri = None
        self.local = None
        uri = str(uri)

        # Data URI
        if uri.startswith("data:"):
            m = _rx_datauri.match(uri)
            self.mimetype = m.group("mime")
            self.data = base64.decodestring(m.group("data"))

        else:

            # Check if we have an external scheme
            if basepath:
                urlParts = urlparse.urlparse(basepath)
            else:
                urlParts = urlparse.urlparse(uri)

            # Drive letters have len==1 but we are looking for things like http:
            if len(urlParts[0])>1:

                # External data
                if basepath:
                    uri = urlparse.urljoin(basepath, uri)

                #path = urlparse.urlsplit(url)[2]
                #mimetype = getMimeType(path)
                urlResponse = urllib2.urlopen(uri)
                self.mimetype = urlResponse.info().get("Content-Type", None).split(";")[0]
                self.uri = urlResponse.geturl()
                self.file = urlResponse

            else:

                # Local data
                if basepath:
                    uri = os.path.normpath(os.path.join(basepath, uri))

                if os.path.isfile(uri):
                    self.uri = uri
                    self.local = uri
                    self.setMimeTypeByName(uri)
                    self.file = open(uri, "rb")

    def getFile(self):
        if self.file is not None:
            return self.file
        if self.data is not None:
            return StringIO.StringIO(self.data)
        return None

    def getData(self):
        if self.data is not None:
            return self.data
        if self.file is not None:
            self.data = self.file.read()
            return self.data
        return None

    def getBasePath(self):
        if self.local:
            return os.path.dirname(os.path.abspath(self.local))
        elif self.uri:
            return self.uri
        return None

    def notFound(self):
        return (self.file is None) and (self.data is None)

    def setMimeTypeByName(self, name):
        " Guess the mime type "
        mimetype = mimetypes.guess_type(name)[0]
        if mimetype is not None:
            self.mimetype = mimetypes.guess_type(name)[0].split(";")[0]

def getFile(*a , **kw):
    file = FileObject(*a, **kw)
    if file.notFound():
        return None
    return file

if __name__=="__main__":
    print getFile("__init__.py")
